#!/usr/bin/env python3
"""
qwencode命令行工具的RESTful API接口
基于FastAPI实现，提供与qwencode命令行工具的接口桥接
"""

from fastapi import FastAPI, HTTPException, BackgroundTasks
from pydantic import BaseModel, Field
from typing import Dict, Any, Optional, List, AsyncGenerator, Tuple
import uvicorn
import asyncio
import os
import sys
from contextlib import asynccontextmanager
import platform
import traceback

# 导入配置文件
from qwencode_config import DEFAULT_PORT, PORT_ENV_VAR, QWEN_COMMAND

# 导入qwencode服务
from qwencode_service import QwencodeService



# 定义请求和响应模型
class QwencodeRequest(BaseModel):
    text: str = Field(..., description="要编码的文本内容")
    encoding_params: Dict[str, Any] = Field(default_factory=dict, description="编码参数")
    stream: bool = Field(False, description="是否使用流式响应")
    working_directory: Optional[str] = Field(None, description="命令执行的工作目录，默认为当前目录")

class QwencodeResponse(BaseModel):
    encoded_text: str = Field(..., description="编码后的文本")
    original_text: str = Field(..., description="原始文本")
    encoding_params: Dict[str, Any] = Field(..., description="使用的编码参数")

class QwencodeStreamChunk(BaseModel):
    encoded_chunk: str = Field(..., description="编码的文本块")
    done: bool = Field(False, description="是否为最后一个块")

# 应用程序生命周期管理
@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时初始化qwencode服务
    print("🔍 尝试初始化qwencode服务...")
    try:
        # 直接检查qwen命令是否存在（已知使用qwen -y）
        import shutil
        qwen_exists = shutil.which(QWEN_COMMAND) is not None
        
        if not qwen_exists:
            print("❌ qwen命令未在系统PATH中找到")
            print("🔒 服务无法启动，必须安装qwen命令")
            sys.exit(1)
        else:
            # 尝试初始化真实服务
            try:
                app.state.qwencode_service = QwencodeService()
                print("✅ 真实qwencode服务已初始化")
            except Exception as e:
                print(f"⚠️  真实qwencode服务初始化失败: {e}")
                print("🔒 服务无法启动")
                sys.exit(1)
    except Exception as e:
        print(f"⚠️  初始化服务时出错: {e}")
        print("🔒 服务无法启动")
        sys.exit(1)
    
    yield
    
    # 关闭时的清理工作
    print("🛑 qwencode API服务已关闭")

# 创建FastAPI应用
app = FastAPI(
    title="Qwencode API",
    description="提供qwencode命令行工具的RESTful API接口",
    version="1.0.0",
    lifespan=lifespan
)

# 健康检查端点
@app.get("/health")
async def health_check():
    """健康检查端点"""
    return {
        "status": "healthy",
        "service": "qwencode-api",
        "timestamp": asyncio.get_event_loop().time()
    }

# 编码文本端点（非流式）
@app.post("/encode", response_model=QwencodeResponse)
async def encode_text(request: QwencodeRequest):
    """
    对文本进行编码
    
    - **text**: 要编码的文本内容
    - **encoding_params**: 编码参数（如格式、选项等）
    - **stream**: 是否使用流式响应（此端点固定为false）
    """
    try:
        print(f"🔄 收到编码请求: 文本长度={len(request.text)}, 参数={request.encoding_params}")
        
        # 调用qwencode服务进行编码
        encoded_text = await app.state.qwencode_service.encode_text(
            request.text,
            request.encoding_params,
            working_directory=request.working_directory
        )
        
        # 返回编码结果
        result = QwencodeResponse(
            encoded_text=encoded_text,
            original_text=request.text,
            encoding_params=request.encoding_params
        )
        
        print(f"✅ 编码请求处理成功")
        return result
    except Exception as e:
        error_msg = f"编码失败: {str(e)}"
        print(f"❌ 编码请求处理失败: {error_msg}")
        raise HTTPException(status_code=500, detail=error_msg)

from fastapi.responses import StreamingResponse
import json

# 流式编码文本端点
@app.post("/encode/stream")
async def encode_text_stream(request: QwencodeRequest):
    """
    流式对文本进行编码并返回结果
    
    - **text**: 要编码的文本内容
    - **encoding_params**: 编码参数（如格式、选项等）
    - **stream**: 是否使用流式响应
    """
    async def stream_generator():
        try:
            print(f"🌊 接收到流式编码请求: {request.text[:50]}{'...' if len(request.text) > 50 else ''}")
            print(f"⚙️  使用参数: {request.encoding_params}")
            print(f"🔄 流式模式: {request.stream}")
            
            # 确保服务已初始化
            if not hasattr(app.state, 'qwencode_service'):
                yield json.dumps({"error": "qwencode服务未初始化"}, ensure_ascii=False) + "\n"
                return
            
            # 根据stream参数决定处理方式
            if request.stream:
                # 使用流式编码
                encoded_chunks = []
                chunk_count = 0
                try:
                    async for chunk in app.state.qwencode_service.encode_text_stream(
                        request.text,
                        request.encoding_params,
                        working_directory=request.working_directory
                    ):
                        # 确保chunk是字符串类型
                        chunk_str = str(chunk) if not isinstance(chunk, str) else chunk
                        encoded_chunks.append(chunk_str)
                        chunk_count += 1
                        
                        # 生成JSON格式的响应块，确保中文不被转义
                        response_chunk = QwencodeStreamChunk(encoded_chunk=chunk_str, done=False)
                        yield json.dumps(response_chunk.dict(), ensure_ascii=False) + "\n"
                        await asyncio.sleep(0.02)  # 防止响应过快
                except Exception as inner_e:
                    print(f"❌ 流式处理内部错误: {str(inner_e)}")
                    print(traceback.format_exc())
                    yield json.dumps({"error": f"流式处理失败: {str(inner_e)}"}, ensure_ascii=False) + "\n"
                    return
                
                # 返回最后一个块，标记为完成
                yield json.dumps(QwencodeStreamChunk(encoded_chunk="", done=True).dict(), ensure_ascii=False) + "\n"
                print(f"✅ 流式编码请求处理成功，共返回 {chunk_count} 个块")
            else:
                # 非流式处理（即使在流式端点中）
                print("ℹ️  虽然在流式端点，但根据stream参数使用非流式处理")
                try:
                    # 调用非流式方法
                    encoded_text = await app.state.qwencode_service.encode_text(
                        request.text,
                        request.encoding_params,
                        working_directory=request.working_directory
                    )
                    
                    # 一次性返回所有内容
                    response_chunk = QwencodeStreamChunk(encoded_chunk=encoded_text, done=True)
                    yield json.dumps(response_chunk.dict(), ensure_ascii=False) + "\n"
                    print(f"✅ 非流式编码请求处理成功")
                except Exception as inner_e:
                    print(f"❌ 非流式处理内部错误: {str(inner_e)}")
                    print(traceback.format_exc())
                    yield json.dumps({"error": f"非流式处理失败: {str(inner_e)}"}, ensure_ascii=False) + "\n"
                    return
        except Exception as e:
            error_msg = f"编码失败: {str(e)}"
            print(f"❌ 编码请求处理失败: {error_msg}")
            print(traceback.format_exc())
            yield json.dumps({"error": error_msg}, ensure_ascii=False) + "\n"
    
    # 使用StreamingResponse处理流式响应
    return StreamingResponse(
        stream_generator(),
        media_type="application/x-ndjson",  # 使用newline-delimited JSON格式
        headers={
            "X-Content-Type-Options": "nosniff",
            "Transfer-Encoding": "chunked"
        }
    )

# 获取服务信息端点
@app.get("/info")
async def get_service_info():
    """
    获取qwencode服务的信息
    """
    return {
        "service_type": "real",
        "executable_path": app.state.qwencode_service.qwencode_path,
        "features": {
            "streaming": True,
            "encoding_params": True
        }
    }

# 批量编码端点已移除

# 主函数，用于直接运行API服务器
if __name__ == "__main__":
    # 获取端口号，从环境变量或配置文件中读取
    port = int(os.getenv(PORT_ENV_VAR, DEFAULT_PORT))
    
    print(f"🚀 启动qwencode API服务器")
    print(f"📊 API文档地址: http://localhost:{port}/docs")
    print(f"❤️  健康检查地址: http://localhost:{port}/health")
    print(f"🔄 编码接口: http://localhost:{port}/encode")
    print(f"🌊 流式编码接口: http://localhost:{port}/encode/stream")
    
    # 启动FastAPI服务器
    uvicorn.run(
        "qwencode_api:app",
        host="0.0.0.0",
        port=port,
        reload=True
    )